home *** CD-ROM | disk | FTP | other *** search
- /* StandardGetFolder example
-
- Steve Falkenburg -- MacDTS
-
- This sample uses the new System 7 CustomGetFile routine
- to provide a StandardGetFolder call to be used by applications
- when the user needs to select a folder instead of a file.
-
- It's written in Think C, but should work in MPW if a few #include
- files are added.
-
- The style of the dialog box is taken from the Human Interface note
- on folder selection.
-
- SJF 5/2/92 added check for empty filename and call to MakeFSSpec
- SJF 5/2/92 added check for refcon in filter and hook routines
- SJF 10/30/91 original coding
- SPD 8/14/95 UPP and minor changes
-
- */
-
- #include <Folders.h>
- #include <Aliases.h>
-
- #include "GzPStrings.h"
-
- #if GENERATINGCFM || USESROUTINEDESCRIPTORS
- # define CreateRoutineDescriptor(info, proc) \
- RoutineDescriptor g##proc##RD = BUILD_ROUTINE_DESCRIPTOR(info, proc)
- # define GetRoutineAddress(proc) (&g##proc##RD)
- #else
- # define GetRoutineAddress(proc) proc
- #endif
-
- /* prototypes */
-
- Boolean SFGetFolder(FSSpec *fSpec);
-
- static void InitStuff(void);
- static pascal short MyDlgHook(short item,DialogPtr theDlg,Ptr userData);
- static pascal Boolean MyModalFilter(DialogPtr theDlg,EventRecord *ev,short *itemHit,Ptr myData);
- static void HitButton(DialogPtr theDlg,short item);
- static pascal Boolean FilterAllFiles(CInfoPBPtr pb, Ptr myDataPtr);
- static void SetSelectButtonName(StringPtr selName,Boolean hilited,DialogPtr theDlg);
- static Boolean SameFile(FSSpec *file1,FSSpec *file2);
- static Boolean GetFSSpecPartialName(FSSpec *file,StringPtr fName);
- static OSErr GetDeskFolderSpec(FSSpec *fSpec,short vRefNum);
- static OSErr MakeCanonFSSpec(FSSpec *fSpec);
- static Boolean ShouldHiliteSelect(FSSpec *fSpec);
-
- /* typedefs */
-
- typedef struct {
- StandardFileReply *replyPtr;
- FSSpec oldSelection;
- } SFData, *SFDataPtr;
-
- /* constants */
-
- #define kSelectItem 10
- #define kSFDlg 129
- #define kCanSelectDesktop true
- #define kSelectStrRsrc 128
- #define kDefaultSelectString "\pSelect"
- #define kDeskStrRsrc 129
- #define kDefaultDeskString "\pDesktop"
- #define kSelectKey 's'
-
- /* globals */
-
- FSSpec gDeskFolderSpec;
- Str255 gSelectString;
- Str255 gDesktopFName;
-
- /*
- * Usage:
- * FSSpec fSpec;
- * Boolean good;
- *
- * extern Boolean SFGetFolder(FSSpec *fSpec);
- * good = SFGetFolder(&fSpec);
- */
-
-
- /* initialize managers */
-
- static void InitStuff(void)
- {
- Handle strHndl;
-
- strHndl = Get1Resource('STR ',kSelectStrRsrc);
- if (ResError()!=noErr || !strHndl || !*strHndl)
- BlockMove(kDefaultSelectString,gSelectString,kDefaultSelectString[0]+1);
- else
- {
- BlockMove(*strHndl,&gSelectString,(long)((unsigned char *)(*strHndl)[0]+1));
- ReleaseResource(strHndl);
- }
-
- strHndl = Get1Resource('STR ',kDeskStrRsrc);
- if (ResError()!=noErr || !strHndl || !*strHndl)
- BlockMove(kDefaultDeskString,gDesktopFName,kDefaultSelectString[0]+1);
- else
- {
- BlockMove(*strHndl,&gDesktopFName,(long)((unsigned char *)(*strHndl)[0]+1));
- ReleaseResource(strHndl);
- }
- }
-
-
- /* do getfile */
-
- Boolean SFGetFolder(FSSpec *fSpec)
- {
- Point where = {-1,-1};
- StandardFileReply sfReply;
- SFData sfUserData;
- OSErr err;
- Boolean targetIsFolder,
- wasAliased;
-
- #if GENERATINGCFM || USESROUTINEDESCRIPTORS
- CreateRoutineDescriptor(uppFileFilterYDProcInfo, FilterAllFiles);
- CreateRoutineDescriptor(uppDlgHookYDProcInfo, MyDlgHook);
- CreateRoutineDescriptor(uppModalFilterYDProcInfo, MyModalFilter);
- #endif
-
- InitStuff();
-
- /* initialize user data area */
-
- sfUserData.replyPtr = &sfReply;
- sfUserData.oldSelection.vRefNum = -9999; /* init to ridiculous value */
-
- CustomGetFile(
- (FileFilterYDUPP)GetRoutineAddress(FilterAllFiles),
- -1,nil,
- &sfReply,
- kSFDlg,
- where,
- (DlgHookYDUPP)GetRoutineAddress(MyDlgHook),
- (ModalFilterYDUPP)GetRoutineAddress(MyModalFilter),
- nil,nil,&sfUserData);
-
-
- if (sfReply.sfGood)
- {
- MakeCanonFSSpec(&sfReply.sfFile); /* spd, August 29, 1995 */
-
- err = ResolveAliasFile(&sfReply.sfFile,true,&targetIsFolder,&wasAliased);
- if (err!=noErr)
- return false;
- }
-
- err = FSMakeFSSpec(sfReply.sfFile.vRefNum,sfReply.sfFile.parID,sfReply.sfFile.name,fSpec);
- if (err!=noErr)
- return false;
-
- return sfReply.sfGood;
- }
-
-
- /* this dialog hook checks the contents of the additional edit fields
- when the user selects a file. The focus of the dialog is changed if one
- of the fields is out of range.
- */
-
- static pascal short MyDlgHook(short item,DialogPtr theDlg,Ptr userData)
- {
- SFDataPtr sfUserData;
- FSSpec curSpec;
- OSType refCon;
-
- refCon = GetWRefCon(theDlg);
- if (refCon!=sfMainDialogRefCon)
- return item;
-
- sfUserData = (SFDataPtr) userData;
-
- if (item==sfHookFirstCall || item==sfHookLastCall)
- return item;
-
- if (item==sfItemVolumeUser) {
- sfUserData->replyPtr->sfFile.name[0] = '\0';
- sfUserData->replyPtr->sfFile.parID = 2;
- sfUserData->replyPtr->sfIsFolder = false;
- sfUserData->replyPtr->sfIsVolume = false;
- sfUserData->replyPtr->sfFlags = 0;
- item = sfHookChangeSelection;
- }
-
- if (!SameFile(&sfUserData->replyPtr->sfFile,&sfUserData->oldSelection)) {
- BlockMove(&sfUserData->replyPtr->sfFile,&curSpec,sizeof(FSSpec));
- MakeCanonFSSpec(&curSpec);
-
- if (curSpec.vRefNum!=sfUserData->oldSelection.vRefNum)
- GetDeskFolderSpec(&gDeskFolderSpec,curSpec.vRefNum);
- SetSelectButtonName(curSpec.name,ShouldHiliteSelect(&curSpec),theDlg);
-
- BlockMove(&sfUserData->replyPtr->sfFile,&sfUserData->oldSelection,sizeof(FSSpec));
- }
-
- if (item==kSelectItem)
- item = sfItemOpenButton;
-
- return item;
- }
-
-
- static pascal Boolean MyModalFilter(DialogPtr theDlg,EventRecord *ev,short *itemHit,Ptr myData)
- {
- Boolean evHandled;
- char keyPressed;
- OSType refCon;
-
- refCon = GetWRefCon(theDlg);
- if (refCon!=sfMainDialogRefCon)
- return false;
-
- evHandled = false;
-
- switch (ev->what)
- {
- case keyDown:
- case autoKey:
- keyPressed = ev->message & charCodeMask;
- if ((ev->modifiers & cmdKey) != 0)
- {
- switch (keyPressed)
- {
- case kSelectKey:
- HitButton(theDlg,kSelectItem);
- *itemHit = kSelectItem;
- evHandled = true;
- break;
- }
- }
- break;
- }
-
- return evHandled;
- }
-
-
- static void HitButton(DialogPtr theDlg,short item)
- {
- short iType;
- ControlHandle iHndl;
- Rect iRect;
- long fTicks;
-
- GetDItem(theDlg,item,&iType,(Handle *)&iHndl,&iRect);
- HiliteControl(iHndl,inButton);
- Delay(5,&fTicks);
- HiliteControl(iHndl,0);
- }
-
-
- static pascal Boolean FilterAllFiles(CInfoPBPtr pb, Ptr myDataPtr)
- {
- if (pb->hFileInfo.ioFlAttrib & (1<<4)) /* file is a directory */
- return false;
-
- return true;
- }
-
-
- static void SetSelectButtonName(StringPtr selName,Boolean hilited,DialogPtr theDlg)
- {
- short iType;
- Handle iHndl;
- Rect iRect;
- Str255 storeName,tempLenStr,tempSelName;
- short btnWidth;
-
- BlockMove(selName,tempSelName,selName[0]+1);
- GetDItem(theDlg,kSelectItem,&iType,&iHndl,&iRect);
-
- /* truncate select name to fit in button */
-
- btnWidth = iRect.right - iRect.left;
- BlockMove(gSelectString,tempLenStr,gSelectString[0]+1);
- PStrCat(tempLenStr, "\p āā ");
- btnWidth -= StringWidth(tempLenStr);
- TruncString(btnWidth,tempSelName,smTruncMiddle);
-
- BlockMove(gSelectString,storeName,gSelectString[0]+1);
-
-
- PStrCat( storeName, "\p ā");
- PStrCat( storeName, tempSelName);
- PStrCat( storeName, "\pā");
-
- SetCTitle((ControlHandle)iHndl,storeName);
-
- SetDItem(theDlg,kSelectItem,iType,iHndl,&iRect);
-
- if (hilited)
- HiliteControl((ControlHandle)iHndl,0);
- else
- HiliteControl((ControlHandle)iHndl,255);
- }
-
-
- static Boolean SameFile(FSSpec *file1,FSSpec *file2)
- {
- if (file1->vRefNum != file2->vRefNum)
- return false;
- if (file1->parID != file2->parID)
- return false;
- if (!EqualString(file1->name,file2->name,false,true))
- return false;
-
- return true;
- }
-
-
- static OSErr GetDeskFolderSpec(FSSpec *fSpec,short vRefNum)
- {
- OSErr err;
-
- fSpec->name[0] = '\0';
- err = FindFolder(vRefNum,kDesktopFolderType,kDontCreateFolder,
- &fSpec->vRefNum,&fSpec->parID);
- if (err!=noErr)
- return err;
-
- return MakeCanonFSSpec(fSpec);
- }
-
-
- static Boolean ShouldHiliteSelect(FSSpec *fSpec)
- {
- if (SameFile(fSpec,&gDeskFolderSpec)) {
- BlockMove(gDesktopFName,fSpec->name,gDesktopFName[0]+1);
- return kCanSelectDesktop;
- }
- else
- return true;
- }
-
-
- static OSErr MakeCanonFSSpec(FSSpec *fSpec)
- {
- DirInfo infoPB;
- OSErr err;
-
- if (fSpec->name[0] != '\0')
- return noErr;
-
- infoPB.ioNamePtr = fSpec->name;
- infoPB.ioVRefNum = fSpec->vRefNum;
- infoPB.ioDrDirID = fSpec->parID;
- infoPB.ioFDirIndex = -1;
- err = PBGetCatInfo((CInfoPBPtr)&infoPB,false);
- fSpec->parID = infoPB.ioDrParID;
-
- return err;
- }
-
-